const $usersContainer = document.querySelector(".users-container");

const iceServer = {
    iceServers: [{ urls: ["stun:ss-turn1.xirsys.com"] }, { username: "CEqIDkX5f51sbm7-pXxJVXePoMk_WB7w2J5eu0Bd00YpiONHlLHrwSb7hRMDDrqGAAAAAF_OT9V0dWR1d2Vi", credential: "446118be-38a4-11eb-9ece-0242ac140004", urls: ["turn:ss-turn1.xirsys.com:80?transport=udp", "turn:ss-turn1.xirsys.com:3478?transport=udp"] }]
};

let localStream;
let pc = {};

function client({
    userMediaOptions = { video: true, audio: true }
} = {}) {
    navigator.mediaDevices.getUserMedia({
        video: userMediaOptions.video,
        audio: userMediaOptions.audio
    }).then(async stream => {
        localStream = stream;

        const socket = io("//");

        // 从socket中取得当前在线用户后，连接这些用户
        socket.on("get current users", event => {
            event.splice(event.indexOf(socket.id), 1); // 去除自己
            console.log("other users", event);
            event.forEach(userId => {
                if (!pc[userId]) {
                    // 连接新增的用户
                    startCall(userId);
                }
            });
        });

        function startCall(identify, createOffer = true) {
            // 已有不再连接
            if (pc[identify]) {
                return;
            }

            pc[identify] = new RTCPeerConnection(iceServer);

            localStream.getTracks().forEach((track) => {
                pc[identify].addTrack(track, localStream);//should trigger negotiationneeded event
            });

            // 显示远程内容
            const $userContainer = document.createElement("div");
            $userContainer.appendChild(
                document.createElement("div").appendChild(
                    document.createTextNode(identify)
                )
            );
            $userContainer.appendChild(document.createElement("br"));
            // 显示的文本
            const $stateText = document.createTextNode(pc[identify].iceConnectionState);
            $userContainer.appendChild(document.createElement("div").appendChild($stateText));

            $userContainer.appendChild(document.createElement("br"));
            let $video;
            if (userMediaOptions.video) {
                $video = document.createElement("video");
                $video.autoplay = true;
                $video.controls = true;
                $userContainer.appendChild($video);
            }
            let $audio;
            if (userMediaOptions.audio) {
                $audio = document.createElement("audio");
                $audio.autoplay = true;
                $userContainer.appendChild($audio);
            }
            $usersContainer.appendChild($userContainer);

            pc[identify].onicecandidate = ({ candidate }) => {
                if (!candidate) return;
                socket.emit('ice candidates', {
                    candidate: candidate,
                    sender: socket.id,
                    to: identify
                });
            };

            // 连接断开清理
            const clear = () => {
                pc[identify].oniceconnectionstatechange = null;
                pc[identify].onnegotiationneeded = null;
                pc[identify].onicecandidate = null;
                pc[identify].ontrack = null;
                // 删除标签
                $usersContainer.contains($userContainer) && $usersContainer.removeChild($userContainer);
                // 从当前连接中删除
                delete pc[identify];
            }

            pc[identify].oniceconnectionstatechange = () => {
                // 设置状态显示,更改dom
                $stateText.textContent = pc[identify].iceConnectionState;
                if (
                    pc[identify].iceConnectionState === "failed" ||
                    pc[identify].iceConnectionState === "disconnected" ||
                    pc[identify].iceConnectionState === "closed"
                ) {
                    clear();
                    // 只有呼叫者需要尝试重新连接
                    if (createOffer) {
                        // 断线重连
                        startCall(identify);
                    }
                }
            };

            pc[identify].ontrack = event => {
                console.log("--------------track", event);
                const stream = event.streams[0];

                const kind = event.track.kind;

                if (kind === "video") {
                    $video.srcObject = stream;
                } else if (kind === "audio") {
                    $audio.srcObject = stream;
                }
            }

            if (createOffer) {
                pc[identify].onnegotiationneeded = async () => {
                    const offer = await pc[identify].createOffer();
                    await pc[identify].setLocalDescription(offer);
                    // console.log(pc[identify].localDescription);
                    socket.emit("sdp", {
                        sender: socket.id,
                        to: identify,
                        description: pc[identify].localDescription
                    });

                }
            }

            setTimeout(() => {
                // 如果一定时间还在new状态表示无法连接或者连接质量极差, 直接结束,不再连接
                if (pc[identify] && pc[identify].iceConnectionState === "new") {
                    clear();
                }
            }, 3000);

            setTimeout(() => {
                // 较长时间还未完成连接直接重试
                if (pc[identify] && pc[identify].iceConnectionState !== "connected") {
                    clear();
                    // 只有呼叫者重试
                    createOffer && startCall(identify);
                }
            }, 30000);

            return;
        }

        socket.on("connect", () => {
            console.log(`${socket.id}: connected`);
        });
        socket.on("sdp", async data => {
            console.log("sdp", data);
            if (data.description.type === "offer") {
                console.log("offer", data);
                startCall(data.sender, false);
                // 创建offer实例
                const description = new RTCSessionDescription(data.description);
                // 设置offer为远程描述
                await pc[data.sender].setRemoteDescription(description);
                // 创建answer
                const answer = await pc[data.sender].createAnswer();
                // 设置answer为本地描述
                await pc[data.sender].setLocalDescription(answer);
                // 发出answer
                socket.emit("sdp", {
                    sender: socket.id,
                    description: pc[data.sender].localDescription,
                    to: data.sender
                });
            } else if (data.description.type === "answer") {
                console.log("answer", data);
                // 设置answer为远程描述
                pc[data.sender].setRemoteDescription(new RTCSessionDescription(data.description));
            }
        });

        socket.on('ice candidates', (data) => {
            var candidate = new RTCIceCandidate(data.candidate);
            // 讲对方发来的协商信息保存
            pc[data.sender].addIceCandidate(candidate).catch();
        })
    }).catch(err => console.log(`
    请给予对应权限或调整您的设置
    错误代码: ${err.message}
    `))
}

export default client;